﻿using UnityEngine;
using System.Collections;
using System.Text;
using System.Collections.Generic;
using Assets.Script.Config;

public enum UnitStateType
{
    Idle,
    SpeedUp,//两边的人移动
    March,//移动
    Search,//攻击时候先往前冲 冲到一定的距离会搜寻最近的人去砍
    Push,// 
    Hurt,//
    MakeSkill,//释放技能动作
    SingSkill,//吟唱动作
    MeleeAttack,//砍
    RemoteAttack,//远程
    CriRemoteAttack,//暴击远程
    Dead,//死亡
    BackToFormation,//
    BackToTroop,
    RushOne,//第一段冲刺
    RushTwo,//第二段冲刺
    RushFinish,//冲刺2结束后待命
}

public class Unit : MonoBehaviour
{
    public Troop Troop
    {
        get { return _troop; }
        set { _troop = value; }
    }

    public UnitStateType UnitState
    {
        get { return _unitState; }
        set { _unitState = value; }
    }

    public int BeAttackNum
    {
        get { return _beAttackNum; }
        set { _beAttackNum = value; }
    }

    private Troop _troop;
    private int _partId;
    private float _trueLookDir;
    private int _actionLookDir;
    private string _nowAction;
    private bool _paperModel;
    private PaperAnimCtrl _paperAnim;
    private Renderer _renderer;
    private Animation _anim;
    private SkinnedMeshRenderer _skinnedMeshRenderer;
    public UnitStateType _unitState;

    private Transform _proShadow;
    
    private float _goBlackTimer;
    public bool _unitDead;

    #region 物理相关
    public bool _usePhy = false;
    // public UnitTroop m_unitTroop = UnitTroop.None; //攻击或防御方
    public bool m_dead = false; //是否死亡
    public PhysObject m_PhysObject = null; //物体碰撞对象
    public Vector3 m_vMoveDir;  //移动方向
    public Vector3 m_vFaceDir;  //面朝方向
    public Unit m_tarUnit; //目标单位
    public Troop m_tarTroop; //目标军队
    public string m_strCharName = ""; //单位名称
    #endregion


    public void Init(Troop troop)
    {
        _troop = troop;
        // PartId = partId;
        if (troop.TroopIndex >= 3)
        {
            _trueLookDir = 180;
        }
        // _trueLookDir = (_trueLookDir + Random.Range(BattleMgr.Instance.ArmyInfoDic[troop.UnitType]._randomLookAtInInitLeft, BattleMgr.Instance.ArmyInfoDic[troop.UnitType]._randomLookAtInInitRight) + 360) % 360;
        _paperModel = BattleMgr.Instance.ArmyInfoDic[troop.UnitType]._paperModel == 1;
        if (_paperModel)
        {
            GameObject paperGo = this.transform.Find("Paper").gameObject;
            paperGo.transform.localEulerAngles = new Vector3(25f, 270f, 0);
            paperGo.AddComponent<PaperAnimCtrl>();
            _paperAnim = paperGo.GetComponent<PaperAnimCtrl>();
            _paperAnim.Init(this);
            _renderer = paperGo.GetComponent<Renderer>();
        }
        else
        {
            _anim = this.GetComponentInChildren<Animation>();
            _skinnedMeshRenderer = this.GetComponentInChildren<SkinnedMeshRenderer>();
            _skinnedMeshRenderer.sharedMaterial = BattleMgr.Instance.GetUnitMat(troop.UnitType, troop.IsLeft);
        }
        _unitState = UnitStateType.Idle;
        ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionIdle,1, true, false, 0, false, true);
        // _tempBattleNode = initBattleNode;
        // GetBattleNodes();
        m_PhysObject = new PhysObject();
        m_PhysObject.Init(this);
        m_PhysObject.m_phyMoveState = PhysObject.phyMoveState.Moving;
        InitProShadow();
    }

    private void ChangeActionAndLookDir(float trueLookAngle, string unitAction,float speed, bool loopPlay, bool needCheck, float needCheckTimeOrFrame, bool needCheckFinish, bool mustReset = false)
    {
        if (_paperModel)
        {
            int actionLookDir = Mathf.FloorToInt(((trueLookAngle + 22.5f) % 360) / 45f) * 45;
            if (_actionLookDir != actionLookDir || unitAction != _nowAction || mustReset)
            {
                _actionLookDir = actionLookDir;
                StringBuilder sb = new StringBuilder();
                sb.Append(BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._prefabName);
                sb.Append("_");
                sb.Append(unitAction);
                sb.Append("_");
                float needShowDir = (_actionLookDir + 90) % 360;
                sb.Append(needShowDir);
                //如果沒有這個動畫那麽返回
                if (!BattleMgr.Instance.PaperTroopMatDic.ContainsKey(sb.ToString()))
                    return;

                _nowAction = unitAction;
                _renderer.sharedMaterial = BattleMgr.Instance.PaperTroopMatDic[sb.ToString()];
                _paperAnim.ResetAnim(loopPlay, BattleMgr.Instance.PaperTroopMatDic[sb.ToString()], needCheck, needCheckTimeOrFrame, needCheckFinish);
                switch (unitAction)
                {
                    case BattleSettings._unitActionIdle:
                        _paperAnim.RandomChangeActionFrameOrSpeed(0, 15, 0.1f);
                        break;
                    case BattleSettings._unitActionRun:
                        _paperAnim.RandomChangeActionFrameOrSpeed(0, 15, 0.1f);
                        break;
                    case BattleSettings._unitActionA1:
                    case BattleSettings._unitActionA2:
                    case BattleSettings._unitActionA3:
                    case BattleSettings._unitActionWalk:
                        _paperAnim.RandomChangeActionFrameOrSpeed(0, 0, 0.15f);
                        break;
                }
                switch ((int)_paperAnim.RowNum)
                {
                    case 4:
                        _paperAnim.gameObject.transform.localScale = new Vector3(1.25f, 1.25f, 1.25f) * BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._baseScale;
                        break;
                    case 5:
                        _paperAnim.gameObject.transform.localScale = new Vector3(1f, 1f, 1f) * BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._baseScale;
                        break;
                    case 6:
                        _paperAnim.gameObject.transform.localScale = new Vector3(0.833f, 0.833f, 0.833f) * BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._baseScale;
                        break;
                }
            }
        }
        else
        {
            if (unitAction != _nowAction || mustReset || _actionLookDir != trueLookAngle)
            {
                string animName = _troop.UnitType + "@" + unitAction.ToString();
                if (_anim.GetClip(animName) != null) 
                {
                    this.transform.eulerAngles = new Vector3(0, trueLookAngle, 0);
                    _actionLookDir = (int)trueLookAngle;
                    if (loopPlay)
                    {
                        _anim.wrapMode = WrapMode.Loop;
                    }
                    else
                    {
                        _anim.wrapMode = WrapMode.Once;
                    }
                    if (mustReset)
                        _anim.Stop();

                    _anim.Play(animName);
                    _anim[animName].speed = speed;
                    _nowAction = unitAction;
                }
            }
        }
    }

    private float GetRunAniStateSpeed(float moveSpeed) 
    {
        float result = 1;
        result = moveSpeed * BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._moveAniSpeed;

        return result;
    }

    public void InToHurtType()
    {
        if (_unitState == UnitStateType.Hurt || _unitState == UnitStateType.Dead)
        {
            return;
        }
        //if (BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._useNodesNum >= 19)
        {
            _unitState = UnitStateType.Hurt;
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionHurt,1, false, false, 0, false, true);
            AddInterval(delegate()
            {
                if (_unitState == UnitStateType.Hurt)
                {
                    _unitState = UnitStateType.Idle;
                    if (_troop.TroopIndex >= 3)
                    {
                        _trueLookDir = 180f;
                    }
                    else
                    {
                        _trueLookDir = 0f;
                    }
                    ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionIdle,1, true, false, 0, false, true);
                }
            }, 1.067f);
        }
    }

    private float _backToFormationTime;
    private Vector3 _backToFormationVec3;
    public float m_backToFormationTime
    {
        get { return _backToFormationTime; }
    }
    public void BackToFormation(Vector3 targetPos)
    {
        bool needMove = true;
        int unitUseNodes = BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._useNodesNum;
        if (unitUseNodes == 5)
        {
            if (Vector3.Distance(targetPos, this.transform.position) <= BattleSettings._smallUnitOffsetLength)
            {
                needMove = false;
            }
        }
        else if (unitUseNodes == 13)
        {
            if (Vector3.Distance(targetPos, this.transform.position) <= BattleSettings._mediumUnitOffsetLength)
            {
                needMove = false;
            }
        }
        else if (unitUseNodes == 19)
        {
            if (Vector3.Distance(targetPos, this.transform.position) <= BattleSettings._bigUnitOffsetLength)
            {
                needMove = false;
            }
        }
        if (needMove)
        {
            _unitState = UnitStateType.BackToFormation;
            _backToFormationVec3 = targetPos - this.transform.position;
            _moveSpeed = BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * Random.Range(0.9f, 1.1f);
            float length = Vector3.Distance(targetPos, this.transform.position);
            float normalMoveTime = length / _moveSpeed;
            //_backToFormationVec3 /= normalMoveTime;
            //_backToFormationTime = BattleMgr.Instance.Timer + normalMoveTime;

            float moveTime = Random.Range(2.2f, 3.0f);
            if (normalMoveTime < moveTime)
            {
                _backToFormationVec3 /= normalMoveTime;
                _backToFormationTime = BattleMgr.Instance.Timer + normalMoveTime;
            }
            else
            {
                _backToFormationVec3 /= moveTime;
                _backToFormationTime = BattleMgr.Instance.Timer + moveTime;
            }
            _trueLookDir = BattleMgr.GetAngle(targetPos - this.transform.position);
            float speed = Vector3.Distance(targetPos, this.transform.position) / moveTime;
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionRun, GetRunAniStateSpeed(speed), true, false, 0, false, true);
            _usePhy = false;
            _canMove = true;
        }
        else
        {
            _unitState = UnitStateType.Idle;
            if (_troop.TroopIndex >= 3)
            {
                _trueLookDir = 180f;
            }
            else
            {
                _trueLookDir = 0f;
            }
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionIdle, 1,true, false, 0, false, true);
        }
    }

    private float _moveSpeed;
    private float _speedUpValue;
    private float _moveFixNum;
    private float _targetZ;
    private bool _goForward;
    private bool _canMove;
    private float _marchNextCheckTime;
    private bool _mustGetTarget;

    public float _toZeroPointLength;
    public void DoMarch(float targetZ, bool goForward, float moveFixNum)
    {
        _moveSpeed = BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * Random.Range(0.9f, 1.1f);
        _speedUpValue = Mathf.Abs(this.transform.position.x) / 3f * Random.Range(0.95f, 1.05f);
        _moveSpeed += _speedUpValue;
        _targetZ = targetZ;
        _moveFixNum = moveFixNum;
        if (_targetZ < 0)
        {
            _targetZ += Random.Range(1.5f, 2f);
        }
        else
        {
            _targetZ += Random.Range(-2f, -1.5f);
        }
        _goForward = goForward;
        _unitState = UnitStateType.SpeedUp;
        _speedUpFinishTime = BattleMgr.Instance.Timer + 1.5f;
        _marchNextCheckTime = 0f;
        _mustGetTarget = false;
        _canMove = true;
        if (_troop.TroopIndex >= 3)
        {
            _trueLookDir = 180f;
        }
        else
        {
            _trueLookDir = 0f;
        }
        ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionRun, GetRunAniStateSpeed(_moveSpeed), true, false, 0, false, true);
    }

    private float _rushOneFinishTime;

    public void DoRushOne(float length, bool goForward, float moveFixNum)
    {
        _moveSpeed = BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed;
        _goForward = goForward;
        float targetLength = length - 9f;
        float needTime = targetLength / _moveSpeed;
        if (_goForward)
        {
            _targetZ = targetLength + this.transform.position.z;
        }
        else
        {
            _targetZ = this.transform.position.z - targetLength;
        }
        _unitState = UnitStateType.RushOne;
        _rushOneFinishTime = BattleMgr.Instance.Timer + needTime;
        _canMove = true;
        if (_troop.TroopIndex >= 3)
        {
            _trueLookDir = 180f;
        }
        else
        {
            _trueLookDir = 0f;
        }
        ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionRun, GetRunAniStateSpeed(_moveSpeed), true, false, 0, false, true);
    }

    private float _rushTwoFinishTime;

    public void DoRushTwo()
    {
        _moveSpeed = _moveSpeed * 1.5f;
        float targetLength = 9 + Random.Range(1.5f, 4.5f);
        float needTime = targetLength / _moveSpeed;
        if (_goForward)
        {
            _targetZ = targetLength + this.transform.position.z;
        }
        else
        {
            _targetZ = this.transform.position.z - targetLength;
        }
        _unitState = UnitStateType.RushTwo;
        _rushTwoFinishTime = BattleMgr.Instance.Timer + needTime;
        ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionA1, GetRunAniStateSpeed(_moveSpeed), true, false, 0, false, true);
        if (!_paperModel)
        {
            AddInterval(OnActionFrameCheck, needTime/2);
        }
    }

    private float _speedUpFinishTime;

    public bool CheckSearchTargetEnemy()
    {
        List<Unit> targetUnitList = BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].LiveUnitList;
        float minDis = 10000f;
        Unit tempUnit = null;
        for (int i = 0; i < targetUnitList.Count; i++)
        {
            float dis = Vector3.Distance(this.transform.position, targetUnitList[i].transform.position);
            if (dis < minDis)
            {
                minDis = dis;
                tempUnit = targetUnitList[i];
            }
        }
        if (_mustGetTarget || minDis < BattleSettings.Instance._physicDataDic[_troop.UnitType]._radius + BattleSettings.Instance._physicDataDic[BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].UnitType]._radius + 0.5f)
        {
            if (tempUnit != null)
            {
                m_tarUnit = tempUnit;
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }

    private BattleEffect _remoteBattleEffect;
    private int _remoteUseActionIndex;
    private bool _remoteTargetCanFly;
    private bool _remoteIsCri = false;
    public void DoRemote(int useAttackActionIndex, bool targetUnitCanFly,bool isCri)
    {
        _unitState = UnitStateType.RemoteAttack;
        _remoteUseActionIndex = useAttackActionIndex;
        _remoteTargetCanFly = targetUnitCanFly;
        _remoteIsCri = isCri;
        m_tarUnit = BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].GetRandomUnit();
        _trueLookDir = BattleMgr.GetAngle(m_tarUnit.transform.position - this.transform.position);
        ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[_troop.UnitType][useAttackActionIndex];
        _remoteBattleEffect = ConfigManager.Instance.BattleEffectLoader.GetInfoById(ai._effectId);
        

        ChangeActionAndLookDir(_trueLookDir, "a" + useAttackActionIndex,1, false, true, ai._attackCheckTime, true);
        if (!_paperModel)
        {
            AddInterval(delegate()
            {
                OnActionFrameCheck();
            }, ai._attackCheckTime);
            AddInterval(delegate()
            {
                OnActionFrameCheck();
            }, ai._attackCheckTime + 0.2f);
            AddInterval(delegate()
            {
                OnActionFrameCheck();
            }, ai._attackCheckTime + 0.4f);

            AddInterval(delegate()
            {
                OnActionFinishCheck();
            }, ai._lastTime);
        }
    }




    private int _beAttackNum;

 
    private Unit _attackMeUnit;
    public void BeAttack(Unit unit)
    {
        if (_attackMeUnit == null)
        {
            _attackMeUnit = unit;
        }
        _beAttackNum += 1;
    }

    public void DoSearch()
    {
        if (_unitState == UnitStateType.SpeedUp)
        {
            _moveSpeed -= _speedUpValue;
        }
        _unitState = UnitStateType.Search;
    }

    public void DoSkillAction()
    {
        if (_troop.TroopIndex >= 3)
        {
            _trueLookDir = 180f;
        }
        else
        {
            _trueLookDir = 0f;
        }
        _unitState = UnitStateType.MakeSkill;
        ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[_troop.UnitType][0];
        ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionS1, 1,false, true, ai._attackCheckTime, true);
        if (!_paperModel)
        {
            AddInterval(OnActionFrameCheck, ai._attackCheckTime);
            AddInterval(OnActionFinishCheck, ai._lastTime);
        }
    }

    public void DoSingSkillAction()
    {
        if (_troop.TroopIndex >= 3)
        {
            _trueLookDir = 180f;
        }
        else
        {
            _trueLookDir = 0f;
        }
        _unitState = UnitStateType.SingSkill;
        ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[_troop.UnitType][0];
        ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionS1, 1, false, true, ai._attackCheckTime, true,true);
        if (!_paperModel)
        {
            AddInterval(OnActionFrameCheck, ai._lastTime);
        }
    }

    public bool CheckFightLength()
    {
        if (_unitState != UnitStateType.Search)
        {
            return false;
        }
        if (m_tarUnit == null || m_tarUnit._unitState == UnitStateType.Dead)
        {
            return false;
        }
        if (Mathf.Pow(m_PhysObject.m_fRadius + m_tarUnit.m_PhysObject.m_fRadius, 2) >= Mathf.Pow(transform.position.x - m_tarUnit.transform.position.x, 2) + Mathf.Pow(transform.position.z - m_tarUnit.transform.position.z, 2))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public void FixedMarchSpeed()
    {
        if (_unitState == UnitStateType.March)
        {
            // _moveSpeed *= (0.45f + _moveFixNum * 0.55f);
            _moveSpeed = BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * (0.45f + _moveFixNum * 0.55f) + BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * Random.Range(-0.2f, 0.2f);
        }
        else if (_unitState == UnitStateType.Search)
        {
            // _moveSpeed *= (0.65f + _moveFixNum * 0.35f);
            _moveSpeed = BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * (0.65f + _moveFixNum * 0.35f) + BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * Random.Range(-0.2f, 0.2f);
        }
        else if (_unitState == UnitStateType.SpeedUp)
        {
            _unitState = UnitStateType.March;
            // _moveSpeed = (_moveSpeed - _speedUpValue) * (0.45f + _moveFixNum * 0.55f);
            _moveSpeed = BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * (0.45f + _moveFixNum * 0.55f) +BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._maxMoveSpeed * Random.Range(-0.2f, 0.2f);
        }
    }

    public void DoAttack()
    {
        _unitState = UnitStateType.MeleeAttack;
        _troop.StartMeleeAttack();
        if (BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._attackPattern == BattleSettings._attackPat_Spec)
        {
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionA1,1, false, false, 0, false);
            string targetTroopAttackPat = BattleMgr.Instance.ArmyInfoDic[BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].UnitType]._attackPattern;
            BattleEffect be;
            float actionLastTime;
            if (targetTroopAttackPat == BattleSettings._attackPat_Spec)
            {
                ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionA2,1, true, false, 0, false);
                ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[_troop.UnitType][2];
                be = ConfigManager.Instance.BattleEffectLoader.GetInfoById(ai._effectId);
                actionLastTime = ai._lastTime;
            }
            else
            {
                ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionA1,1, true, false, 0, false);
                ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[_troop.UnitType][1];
                be = ConfigManager.Instance.BattleEffectLoader.GetInfoById(ai._effectId);
                actionLastTime = ai._lastTime;
            }
            float checkTime = 0;
            for (int i = 0; i < be._battleEffectPartList.Count; i++)
            {
                BattleEffectPart bep = ConfigManager.Instance.BattleEffectPartLoader.GetInfoById(be._battleEffectPartList[i]);
                GameObject effect = Instantiate(BattleMgr.Instance.EffectPartGoDic[bep._effectPartId]);
                checkTime = bep._checkTime;
                effect.transform.position = this.transform.position;
                effect.transform.localEulerAngles = this.transform.localEulerAngles;
            }
            if (BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._paperModel != 1)
            {
                AddInterval(delegate()
                {
                    OnActionFrameCheck();
                }, checkTime);
                AddInterval(delegate()
                {
                    OnActionFinishCheck();
                }, actionLastTime);
            }
        }
        else
        {
            ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[_troop.UnitType][1];
            if (_troop.AttackPattern == BattleSettings._attackPat_Spec || _troop.UnitType == BattleSettings._titans)
            {
                ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionA1,1, false, true, ai._attackCheckTime, false);
                if (!_paperModel)
                {
                    AddInterval(delegate()
                    {
                        List<Unit> beAttackUnitList = BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].GetBeAttackUnitList(this, m_tarUnit, 1);
                        _troop.MeleeAttackFinish(this, beAttackUnitList);
                    }, ai._attackCheckTime);
                    // AddInterval(OnActionFinishCheck, ai._lastTime);
                    AddInterval(delegate()
                    {
                        OnActionFinishCheck();
                    }, ai._lastTime);
                }

            }
            else
            {
                ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionA1,1, true, true, ai._attackCheckTime, false);
                if (!_paperModel)
                {
                    AddInterval(delegate()
                    {
                        List<Unit> beAttackUnitList = BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].GetBeAttackUnitList(this, m_tarUnit, 1);
                        _troop.MeleeAttackFinish(this, beAttackUnitList);
                    }, ai._attackCheckTime);
                    // AddInterval(OnActionFinishCheck, ai._lastTime);
                }
            }
        }
    }

    public void OnActionFrameCheck()
    {
        switch (_unitState)
        {
            case UnitStateType.RemoteAttack:
                for (int j = 0; j < _troop._oneShootNum; j++)
                {
                    for (int i = 0; i < _remoteBattleEffect._battleEffectPartList.Count; i++)
                    {
                        BattleEffectPart bep = ConfigManager.Instance.BattleEffectPartLoader.GetInfoById(_remoteBattleEffect._battleEffectPartList[i]);
                        if (bep._isRemoteObj)
                        {
                            GameObject remoteGo = Instantiate(BattleMgr.Instance.EffectPartGoDic[bep._effectPartId]) as GameObject;
                            remoteGo.transform.localScale = remoteGo.transform.localScale * 1;
                            remoteGo.AddComponent<FlyItem>();
                            FlyItem fi = remoteGo.GetComponent<FlyItem>();
                            ActionInfo ai = BattleMgr.Instance.BattleActionInfoDic[_troop.UnitType][_remoteUseActionIndex];
                            int targetUnitUseNodes = BattleMgr.Instance.ArmyInfoDic[m_tarUnit.Troop.UnitType]._useNodesNum;
                            Vector3 targetOffset;
                            if (targetUnitUseNodes == 5)
                            {
                                targetOffset = new Vector3(1.5f * Random.Range(-1f, 1f), 0, 1.5f * Random.Range(-1f, 1f));
                            }
                            else if (targetUnitUseNodes == 13)
                            {
                                targetOffset = new Vector3(4f * Random.Range(-1f, 1f), 0, 4f * Random.Range(-1f, 1f));
                            }
                            else
                            {
                                targetOffset = new Vector3(7f * Random.Range(-1f, 1f), 0, 7f * Random.Range(-1f, 1f));
                            }
                            fi.InitParabola(this.transform.position, m_tarUnit.transform.position + targetOffset, bep._moveSpeed * Random.Range(0.9f, 1.1f), ai._attackAngle, _remoteTargetCanFly, OnRemoteFlyItemArrival);
                            _troop.RemoteStart(bep._moveSpeed);
                        }
                    }
                }
                break;
            case UnitStateType.MeleeAttack:
                List<Unit> beAttackUnitList = BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].GetBeAttackUnitList(this, m_tarUnit, 1);
                _troop.MeleeAttackFinish(this, beAttackUnitList);
                break;
            case UnitStateType.MakeSkill:
                _troop.OnSkillActionCheck();
                break;
            case UnitStateType.RushTwo:
                _mustGetTarget = true;
                CheckSearchTargetEnemy();
                List<Unit> beAttackUnit = BattleMgr.Instance.TroopDic[_troop.FightTargetIndex].GetBeAttackUnitList(this, m_tarUnit, 1);
                _troop.RushAttackFinish(this, beAttackUnit);
                break;
            case UnitStateType.SingSkill:
                if (_troop.AllUnitSameState(UnitStateType.SingSkill)) 
                {
                    _troop.OnSingActionCheck();
                }
                break;
        }
    }

    public void OnRemoteFlyItemArrival(FlyItem flyItem)
    {
        for (int i = 0; i < _remoteBattleEffect._battleEffectPartList.Count; i++)
        {
            BattleEffectPart bep = ConfigManager.Instance.BattleEffectPartLoader.GetInfoById(_remoteBattleEffect._battleEffectPartList[i]);
            if (bep._isTrigger)
            {
                if (bep._attackFlyOrGround == 3 || (bep._attackFlyOrGround == 1 && _remoteTargetCanFly) || (bep._attackFlyOrGround == 2 && !_remoteTargetCanFly))
                {
                    GameObject effectGo = Instantiate(BattleMgr.Instance.EffectPartGoDic[bep._effectPartId]) as GameObject;
                    effectGo.transform.position = flyItem.transform.position;
                    if (bep._needChangeRotate)
                    {
                        effectGo.transform.localEulerAngles = new Vector3(0f, flyItem.RemoteDir, 0f);
                    }
                }
            }
        }
        flyItem.gameObject.SetActive(false);
        _troop.RmoteAttackArrived();
    }

    public void OnActionFinishCheck()
    {
        if (_unitState != UnitStateType.Dead)
        {
            _unitState = UnitStateType.Idle;
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionIdle,1, true, false, 0, false, true);
        }
    }

    public void IntoMoveIdle()
    {
        _unitState = UnitStateType.Idle;
        _usePhy = false;
    }

    public void IntoRushFinish() 
    {
        _unitState = UnitStateType.RushFinish;

    }

    public void BackToOriginalPos(Vector3 targetPos)
    {
        _unitState = UnitStateType.Idle;
        _usePhy = false;
        this.transform.position = targetPos;
        if (_troop.TroopIndex >= 3)
        {
            _trueLookDir = 180f;
        }
        else
        {
            _trueLookDir = 0f;
        }
        ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionIdle,1, true, false, 0, false);
    }

    public delegate void TimeInterval();
    private Dictionary<TimeInterval, float> _timeIntervalDic = new Dictionary<TimeInterval, float>();
    public void AddInterval(TimeInterval interval, float time)
    {
        if (interval != null)
        {
            _timeIntervalDic[interval] = BattleMgr.Instance.Timer + time;
        }
    }

    public void RemoveInterval(TimeInterval interval)
    {
        if (interval != null)
        {
            if (_timeIntervalDic.ContainsKey(interval))
            {
                _timeIntervalDic.Remove(interval);
            }
        }
    }

    void FixedUpdate()
    {
        if (!BattleStage.g_InBattle)
        {
            return;
        }

        if (_timeIntervalDic.Count > 0)
        {
            List<TimeInterval> timeIntervalKeyList = new List<TimeInterval>(_timeIntervalDic.Keys);
            for (int i = 0; i < timeIntervalKeyList.Count; i++)
            {
                if (_timeIntervalDic[timeIntervalKeyList[i]] <= BattleMgr.Instance.Timer)
                {
                    TimeInterval ti = timeIntervalKeyList[i];
                    _timeIntervalDic.Remove(timeIntervalKeyList[i]);
                    ti();
                }
            }
        }
    }

    void Update()
    {
        if (!BattleStage.g_InBattle)
        {
            return;
        }
        if (_unitDead)
        {
            return;
        }
        if (m_PhysObject != null && _usePhy)
        {
            m_PhysObject.Update();
            if (BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._useNodesNum != 19)
            {
                transform.position += m_PhysObject.GetUpdateAddedPos();
            }
        }

        if (_unitState == UnitStateType.SpeedUp || _unitState == UnitStateType.March)
        {
            if (_unitState == UnitStateType.SpeedUp)
            {
                if (BattleMgr.Instance.Timer >= _speedUpFinishTime)
                {
                    _moveSpeed -= _speedUpValue;
                    _unitState = UnitStateType.March;
                }
            }
            if (BattleMgr.Instance.Timer >= _marchNextCheckTime)
            {
                if (_goForward)
                {
                    _mustGetTarget = (this.transform.position.z >= _targetZ);
                }
                else
                {
                    _mustGetTarget = (this.transform.position.z <= _targetZ);
                }
                bool getTarget = CheckSearchTargetEnemy();
                if (getTarget)
                {
                    DoSearch();
                    return;
                }
                else
                {
                    if (_mustGetTarget == true)
                    {
                        _unitState = UnitStateType.Idle;
                    }
                    else
                    {

                        _marchNextCheckTime = BattleMgr.Instance.Timer + 0.1f;
                        if (_goForward)
                        {
                            this.transform.position += Vector3.forward * Time.deltaTime * _moveSpeed;
                        }
                        else
                        {
                            this.transform.position += Vector3.back * Time.deltaTime * _moveSpeed;
                        }
                    }
                }
            }
            else
            {
                if (_goForward)
                {
                    this.transform.position += Vector3.forward * Time.deltaTime * _moveSpeed;
                }
                else
                {
                    this.transform.position += Vector3.back * Time.deltaTime * _moveSpeed;
                }
            }
        }
        else if (_unitState == UnitStateType.RushOne)
        {
            if (BattleMgr.Instance.Timer >= _rushOneFinishTime)
            {
                DoRushTwo();
            }
            else
            {
                if (_goForward)
                {
                    this.transform.position += Vector3.forward * Time.deltaTime * _moveSpeed;
                }
                else
                {
                    this.transform.position += Vector3.back * Time.deltaTime * _moveSpeed;
                }
            }
        }
        else if (_unitState == UnitStateType.RushTwo)
        {
            if (BattleMgr.Instance.Timer >= _rushTwoFinishTime)
            {
                IntoRushFinish();
            }
            else
            {
                if (_goForward)
                {
                    this.transform.position += Vector3.forward * Time.deltaTime * _moveSpeed;
                }
                else
                {
                    this.transform.position += Vector3.back * Time.deltaTime * _moveSpeed;
                }
            }
        }
        else if (_unitState == UnitStateType.Search)
        {
            if (m_tarUnit.UnitState == UnitStateType.Dead)
            {
                m_tarUnit = null;
            }
            if (m_tarUnit == null)
            {
                _mustGetTarget = true;
                bool getTarget = CheckSearchTargetEnemy();
                if (!getTarget)
                {
                    IntoMoveIdle();
                    return;
                }
            }
            Vector3 moveDir = (m_tarUnit.transform.position - this.transform.position).normalized;
            m_vFaceDir = moveDir;
            m_vMoveDir = moveDir;
            this.transform.position += moveDir * Time.deltaTime * _moveSpeed;
            _trueLookDir = BattleMgr.GetAngle(moveDir);
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionRun, GetRunAniStateSpeed(_moveSpeed), true, false, 0, false);
            if (CheckFightLength())
            {
                if (_troop.UnitType == BattleSettings._titans)
                {
                    IntoPushState();
                }
                else
                {
                    _troop.TroopTouch();
                    DoAttack();
                }
            }
        }
        else if (_unitState == UnitStateType.Dead)
        {
            if (BattleMgr.Instance.Timer <= _goBlackTimer)
            {
                if (_paperModel)
                {
                    Color c = _renderer.material.color;
                    c.r -= Time.deltaTime * 0.1f;
                    c.g -= Time.deltaTime * 0.1f;
                    c.b -= Time.deltaTime * 0.1f;
                    c.a -= (Time.deltaTime * 0.5f) / 2f;
                    _renderer.material.SetColor("_Color", c);
                }
                else
                {

                }
            }
            else
            {
                if (_paperModel)
                {
                    _paperAnim.gameObject.GetComponent<MeshRenderer>().enabled = false;
                    this.transform.Find("ProShadow").gameObject.SetActive(false);
                }
                else
                {
                
                }
                _unitDead = true;
            }
        }
        else if (_unitState == UnitStateType.BackToFormation)
        {
            if (BattleMgr.Instance.Timer >= _backToFormationTime)
            {
                _unitState = UnitStateType.Idle;
                if (_troop.TroopIndex >= 3)
                {
                    _trueLookDir = 180f;
                }
                else
                {
                    _trueLookDir = 0f;
                }
                ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionIdle,1, true, false, 0, false, true);
            }
            else
            {
                this.transform.position += _backToFormationVec3 * Time.deltaTime;
            }
        }
        else if (_unitState == UnitStateType.Push)
        {
            if (BattleMgr.Instance.Timer >= _finishPushTime)
            {
                _troop.TroopTouch();
                DoAttack();
            }
            else
            {
                if (m_tarUnit.UnitState == UnitStateType.Dead)
                {
                    m_tarUnit = null;
                }
                if (m_tarUnit == null)
                {
                    _mustGetTarget = true;
                    bool getTarget = CheckSearchTargetEnemy();
                    if (!getTarget)
                    {
                        IntoMoveIdle();
                        return;
                    }
                }
                Vector3 moveDir = (m_tarUnit.transform.position - this.transform.position).normalized;
                m_vFaceDir = moveDir;
                m_vMoveDir = moveDir;
                this.transform.position += moveDir * Time.deltaTime * _moveSpeed;
                _trueLookDir = BattleMgr.GetAngle(moveDir);
                ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionRun, GetRunAniStateSpeed(_moveSpeed), true, false, 0, false);
            }
        }
    }

    public float _finishPushTime;
    public void IntoPushState()
    {
        _finishPushTime = BattleMgr.Instance.Timer + 1f;
        _unitState = UnitStateType.Push;
    }

    public void DoDead(Vector3 attackVec3, float attackPower)
    {
        if (_unitState == UnitStateType.Dead)
        {
            return;
        }
        _unitState = UnitStateType.Dead;
        
        _goBlackTimer = BattleMgr.Instance.Timer + 2f;
        DelProShadow();
        AddInterval(delegate()
        {
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionDie,1, false, false, 0, false);
            if (!_paperModel)
            {
                AddInterval(delegate()
                {
                    _skinnedMeshRenderer.enabled = false;
                }, 3f);
            }
            float dis = (attackPower - BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._attackResistance) * 5;
            float angle = 45f;
            float ranValue = 0.2f;
            //if (dis > 0 && _paperModel)
            if (dis > 0)
            {
                if (attackVec3 == this.transform.position)
                {
                    DeadStrength ds = new DeadStrength(this, new Vector3(Random.Range(0f, 1f), 0f, Random.Range(0f, 1f)), dis * 1.5f, dis, angle, ranValue);
                    ds.DoDead();
                }
                else
                {
                    DeadStrength ds = new DeadStrength(this, this.transform.position - attackVec3, dis * 1.5f, dis, angle, ranValue);
                    ds.DoDead();
                }
            }
        }, Random.Range(0f, 0.5f));
    }

    public void DoDead(float attackPower, float lastTime)
    {
        if (_unitState == UnitStateType.Dead)
        {
            return;
        }
        _unitState = UnitStateType.Dead;
        _goBlackTimer = BattleMgr.Instance.Timer + 2f;
        DelProShadow();
        AddInterval(delegate()
        {
            ChangeActionAndLookDir(_trueLookDir, BattleSettings._unitActionDie,1, false, false, 0, false);
            if (!_paperModel)
            {
                AddInterval(delegate()
                {
                    _skinnedMeshRenderer.enabled = false;
                }, 3f);
            }
            float dis = (attackPower - BattleMgr.Instance.ArmyInfoDic[_troop.UnitType]._attackResistance) * 5;
            float angle = 45f;
            float ranValue = 0.2f;
            //if (dis > 0&& _paperModel)
            if (dis > 0)
            {
                if (_attackMeUnit != null)
                {
                    DeadStrength ds = new DeadStrength(this, this.transform.position - _attackMeUnit.transform.position, dis * 1.5f, dis, angle, ranValue);
                    ds.DoDead();
                }
                else
                {
                    Vector3 flyDir;
                    if (_troop.TroopIndex >= 3)
                    {
                        flyDir = this.transform.position + new Vector3(0, 0f, -2.5f);
                    }
                    else
                    {
                        flyDir = this.transform.position + new Vector3(0, 0f, 2.5f);
                    }
                    DeadStrength ds = new DeadStrength(this, this.transform.position - flyDir, dis * 1.5f, dis, angle, ranValue);
                    ds.DoDead();
                }
            }
        }, Random.Range(0f, lastTime));
    }

    public static int UnitSortFromZreo(Unit a, Unit b)
    {
        return a._toZeroPointLength.CompareTo(b._toZeroPointLength);
    }

    private void DelProShadow() 
    {
        GameObject ProShadow = transform.Find("ProShadow").gameObject;
        if (ProShadow != null) 
        {
            ProShadow.SetActive(false);
        }
    }

    private void InitProShadow() 
    {
        _proShadow = transform.Find("ProShadow");
        if (_proShadow != null)
        {
            _proShadow.gameObject.SetActive(true);
            LoclRotation lockRo = _proShadow.GetComponent<LoclRotation>();
            if (lockRo == null)
                lockRo = _proShadow.gameObject.AddComponent<LoclRotation>();

            Vector3 el = (_troop.IsLeft) ? new Vector3(90, -90, 0) : new Vector3(90, 90, 0);
            _proShadow.localEulerAngles = el;
            el = _proShadow.eulerAngles;

            lockRo.LockEulerAngles(el);
        }
    }
}
